"""
    Author:
    Date: 2018-11-08

    服务器管理类
"""

import datetime
import re
import os
import json

from django.conf import settings
from entities.consts import *
from utils import db
from utils import util


API_SERVER_LOG_PATTERN = re.compile('\[(?P<log_time>[\d\-: ]+)\] (?P<log_type>[^:]+): (?P<content>.*)')
API_SERVER_LOG_PATTERN2 = re.compile('\[(?P<log_time>[\d\-: ]+)\] (?P<log_type>[^:]+): service:tv\.(?P<log_api>[\w]+):[^ ]+ \[(?P<log_ip>[\d\.]+)\] \[code:\d+\] (?P<content>.*) \[\]')

# [2019-07-30 12:43:48] time.DEBUG: service:tv.loginWithPhone:0.063086986541748s [223.80.203.113] [code:0] {"service":"tv.loginWithPhone","phone_number":"18363914676","sms_code":"0708","app_version":"113","channel":"yj_origin","device_model":"V1836A, android 28","device_id":"86

def get_action_desp(api):
    """ 根据接口返回行为操作 """
    data = {
        'loginWithPhone': '手机登录',
        'loginWithThirdParty': '微信登录',
        'inviteVipChat': '呼叫用户',
        'acceptVipChat': '接收呼叫',
        'cancelVipChat': '取消呼叫',
        'declineVipChat': '拒绝呼叫',
        'quitVipChat': '退出通话',
        'sendGift': '赠送礼物',
        'buyVideo': '购买视频',
        'followVideo': '关注视频',
        'payWithWeixin': '请求微信支付',
        'payWithAli': '请求支付宝支付',
        'createApplePayOrderId': '请求苹果支付',
        'follow': '关注用户',
        'unfollow': '取消关注用户',
        'updateNickname': '更新昵称',
        'updateSignature': '更新签名',
        'insertToBlacklist': '拉黑用户',
        'removeFromBlacklist': '取消拉黑',
        'shareVideo': '分享视频',
        'uploadAuthInfo': '上传认证资料',
        'uploadVideo': '上传短视频',
        'deleteVideo': '删除短视频',
        'uploadAvatar': '删除头像',
        'chargingChat': '发送私信',
        'reportComplaints': '举报用户',
        'buyVipCard': '购买VIP',
        'publishMoment': '发布动态',
        'deleteMoment': '删除动态',
        'updateGpsLocation': '更新地理位置',
    }
    return data.get(api, None)


def get_user_action_logs(uid, day, mobile, openid):
    """ """
    log_path = f'{settings.API_SERVER_LOG_DIR}/time-{day}.log2'
    if not os.path.exists(log_path):
        return [f'NOT find {log_path}!']

    lines = open(log_path, 'r').readlines()
    result = []
    max_result = 100
    for line in lines:
        m = API_SERVER_LOG_PATTERN2.match(line)
        if m is not None:
            g = m.groupdict()
            log_time = g['log_time']
            log_type = g['log_type']
            log_ip = g['log_ip']
            log_api = g['log_api']
            content = json.loads(g['content'])

            # 处理登录数据
            if log_api == 'loginWithPhone':
                if content.get('phone_number', None) != mobile:
                    continue

                log_action = '手机登录'
            elif log_api == 'loginWithThirdParty':
                if content.get('openid', None) != openid:
                    continue

                log_action = '微信登录'
            else:
                request_uid = content.get('uid', None)
                if request_uid is None or int(request_uid) != int(uid):
                    continue

                log_action = get_action_desp(log_api)
                if log_action is None:
                    continue

            # 移除多余数据
            if 'uid' in content:
                del content['uid']
            if 'token' in content:
                del content['token']
            if 'sign' in content:
                del content['sign']
            if 'timestamp' in content:
                del content['timestamp']
            if 'service' in content:
                del content['service']

            log_info = {
                'time': log_time,
                'type': log_type,
                'api': log_api,
                'ip': log_ip,
                'port': 80,
                'action': log_action,
                'detail': content,
            }

            result.append(log_info)
            if len(result) > max_result:
                break

    result.reverse()
    return result


def get_server_archive_data(count, field, unit):
    """ 获取服务器端归档数据 """
    data = []
    records = get_server_daily_archive(count)
    if len(records) >= 2:
        temp = records[0][field]
        for record in records[1:]:
            date = record['create_date']
            total_user_count = record[field]
            value = temp - total_user_count
            temp = total_user_count
            data.append((date, value, unit))
    return data


def get_api_server_log_files(ignore_hidden_files=True):
    """ 获取api_server的日志文件列表 """
    log_files = os.listdir(settings.API_SERVER_LOG_DIR)
    if ignore_hidden_files:
        log_files = list(filter(lambda x: not x.startswith('.'), log_files))
    log_files.sort(reverse=True)
    return log_files


def get_api_server_log(log_name, read_line_count=10):
    """ 获取api_server的指定日志的内容"""
    log_path = f'{settings.API_SERVER_LOG_DIR}/{log_name}'
    if not os.path.exists(log_path):
        return [f'NOT find {log_name}!']

    total_lines = open(log_path, 'r').readlines()
    total_line_count = len(total_lines)
    read_line_count = min(total_line_count, read_line_count)
    lines = total_lines[-read_line_count:]
    result = []
    for i, line in enumerate(lines):
        lineno = total_line_count - read_line_count + i + 1
        m = API_SERVER_LOG_PATTERN.match(line)
        if m is not None:
            g = m.groupdict()
            log_info = {
                'lineno': lineno,
                'time': g['log_time'],
                'type': g['log_type'],
                'content': g['content'][:800],
            }
        else:
            log_info = {
                'lineno': lineno,
                'log_time': '',
                'log_type': '',
                'content': line,
            }

        result.append(log_info)

    result.reverse()
    return result


def get_server_daily_archive(count):
    """ 获取服务器的最近几天的每日归档数据 """
    sql = f'''
        SELECT      *
        FROM        cmf_server_daily_archive
        ORDER BY    id DESC
        LIMIT       {count};
    '''
    data = db.query_data_from_db(sql)
    return data if data else []


def get_online_caster_count_per_hour(begin_time, end_time):
    """ 获取主播在指定时间内的每小时的在线数量 """
    records = get_online_caster_count_data(begin_time, end_time)
    data = {}
    b = util.strtotime(begin_time)
    for h in range(24):
        users = set()
        # data[h] = 0
        for record in records:
            uid = int(record['uid'])
            record_begin_time = util.datetimetotime(record['begin_time'])
            record_end_time = util.datetimetotime(record['end_time'])

            hour_begin = b + h*3600
            hour_end = b + (h+1)*3600
            if record_begin_time < hour_begin < record_end_time:
                # data[h] += 1
                users.add(uid)
            if record_begin_time >= hour_begin and record_end_time <= hour_end:
                # data[h] += 1
                users.add(uid)
            if record_begin_time < hour_end < record_end_time:
                # data[h] += 1
                users.add(uid)
        data[h] = len(users)
    return data


def get_online_caster_count_data(begin_time, end_time):
    """ 获取主播在线的数据 """
    settled_data = get_settled_online_caster_count_data(begin_time, end_time)
    unsettled_data = get_unsettled_online_caster_count_data(begin_time, end_time)
    return settled_data + unsettled_data


def get_unsettled_online_caster_count_data(begin_time, end_time):
    """ 获取未归档的主播在线的数据 """
    sql = f'''
        SELECT      u.*
        FROM        cmf_users AS u
        JOIN        cmf_users_auth AS a ON a.uid=u.id
        WHERE       a.status={AUTH_STATUS_CERTIFIED} AND
                    u.is_busy=0;
    '''
    params = {
        'begin_time': begin_time,
        'end_time': end_time,
    }
    records = db.query_data_from_db(sql, params)

    end_time = datetime.datetime.now()
    end_timestamp = util.datetimetotime(end_time)
    data = []
    for record in records:
        begin_time = record['set_busy_time']
        info = {
            'uid': record['id'],
            'begin_time': begin_time,
            'end_time': end_time,
            'online_seconds': end_timestamp - util.datetimetotime(begin_time)
        }
        data.append(info)
    return data


def get_settled_online_caster_count_data(begin_time, end_time):
    """ 获取归档的主播在线的数据 """
    sql = '''
        SELECT      *
        FROM        cmf_users_online_log
        WHERE       end_time>=%(begin_time)s AND
                    begin_time<=%(end_time)s;
    '''
    params = {
        'begin_time': begin_time,
        'end_time': end_time,
    }
    data = db.query_data_from_db(sql, params)
    return data if data else []


def get_call_count_per_hour(begin_time, end_time):
    """ 获取指定时间内每小时的通话数量 """
    records = get_call_data(begin_time, end_time)
    data = {}
    b = util.strtotime(begin_time)
    for h in range(24):
        data[h] = 0
        for record in records:
            record_begin_time = util.datetimetotime(record['begin_time'])
            record_end_time = util.datetimetotime(record['end_time'])

            hour_begin = b + h*3600
            hour_end = b + (h+1)*3600
            if record_begin_time < hour_begin and record_end_time > hour_begin:
                data[h] += 1
            if record_begin_time >= hour_begin and record_end_time <= hour_end:
                data[h] += 1
            if record_begin_time < hour_end and record_end_time > hour_end:
                data[h] += 1
    return data


def get_call_data(begin_time, end_time):
    """ 获取主播在线的数据 """
    sql = '''
        SELECT      *
        FROM        cmf_vchat_call_log
        WHERE       end_time>=%(begin_time)s AND
                    begin_time<=%(end_time)s;
    '''
    params = {
        'begin_time': begin_time,
        'end_time': end_time,
    }
    data = db.query_data_from_db(sql, params)
    return data if data else []


def get_new_user_count_per_hour(begin_time, end_time):
    """ 获取指定时间内每小时的在线主播数量 """
    sql = '''
        SELECT      EXTRACT(HOUR FROM create_time) AS create_hour,
                    COUNT(*) AS role_count
        FROM        cmf_users
        WHERE       create_time>=%(begin_time)s AND
                    create_time<=%(end_time)s
        GROUP BY    create_hour ORDER BY create_hour;
    '''
    params = {
        'begin_time': begin_time,
        'end_time': end_time,
    }
    records = db.query_data_from_db(sql, params)
    if not records:
        return {}

    data = {}
    for record in records:
        hour = record['create_hour']
        count = record['role_count']
        data[hour] = count
    return data


if __name__ == '__main__':
    print('ok')
